package net.yxsoft.controller.pc.sysmgt.common.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.weixin.sdk.kit.IpKit;
import net.yxsoft.resource.AuthuserRes;
import net.yxsoft.model.infrastructure.TsSession;
import net.yxsoft.model.infrastructure.TsUser;
import net.yxsoft.service.infrastructure.LoginService;
import rapid.core.Authuser;

public class LoginDbSessionInterceptor implements Interceptor {
  /**
  * @MethodName: intercept
  * @Description:
  * @param: inv
  * @return void
  * @throws
  * @date 2023/8/31 15:36
  * @author jhf
  */
   public void intercept(Invocation inv) {
     Authuser loginAccount = null;
     Controller c = inv.getController();
     String sessionId = c.getCookie(AuthuserRes.KEY_TS_SESSION_UID);



     if(sessionId != null) {
       loginAccount = getLoginAccountWithSessionId(sessionId);

       if(loginAccount == null) {
         String loginIp = IpKit.getRealIp(c.getRequest());
         loginAccount = loginWithSessionId(sessionId, loginIp);
       }
       if(loginAccount != null) {
         // 用户登录账号
         c.setSessionAttr(Authuser.KEY_USER, loginAccount);
         c.setAttr("loginUser", loginAccount);

       } else {
         c.removeCookie(AuthuserRes.KEY_TS_SESSION_UID); // cookie 登录未成功，证明该 cookie 已经没有用处，删之
       }
     }else{
       c.setSessionAttr(Authuser.KEY_USER, loginAccount);
       c.setAttr("loginUser", loginAccount);
     }
     inv.invoke();
   }
  /**
  * @MethodName: getLoginAccountWithSessionId
  * @Description:
  * @param: sessionId
  * @return rapid.core.Authuser
  * @throws
  * @date 2023/8/31 15:36
  * @author jhf
  */
   public Authuser getLoginAccountWithSessionId(String sessionId) {
     return CacheKit.get(Authuser.KEY_USER, sessionId);
   }

   /**
    * 通过 sessionId 获取登录用户信息
    * sessoin表结构：session(id, accountId, expireAt)
    * <p>
    * 1：先从缓存里面取，如果取到则返回该值，如果没取到则从数据库里面取
    * 2：在数据库里面取，如果取到了，则检测是否已过期，如果过期则清除记录，
    * 如果没过期则先放缓存一份，然后再返回
    */
  public Authuser loginWithSessionId(String sessionId, String loginIp) {
    TsSession session = TsSession.dao.findById(sessionId);
    if(session == null) {      // session 不存在
      return null;
    }
    if(session.isExpired()) {  // session 已过期
      session.delete();    // 被动式删除过期数据，此外还需要定时线程来主动清除过期数据
      return null;
    }

    TsUser user = new TsUser().findById(session.getUserId());
    // 找到 user 并且 是正常状态 才允许登录
    if(user != null && user.isStatusOk()) {
      user.removeSensitiveInfo();                                 // 移除 password 与 salt 属性值
      user.put(AuthuserRes.KEY_TS_SESSION_UID, sessionId);                          // 保存一份 sessionId 到 loginAccount 备用

      Authuser auth = LoginService.INSTANCE.initAuthuser(user);

      CacheKit.put(Authuser.KEY_USER, sessionId, auth);

      return auth;
    }
    return null;
  }
}
